import { Md5 } from "ts-md5";
import { MongodbClient } from "../lib/db.client.mongodb";
import { PgClient } from "../lib/db.client.pg";

import { ENUM_APP, ENUM_TON_ORDER, TonOrder, TonSku, User } from "qqlx-core";
import { getConditionMatchEnum, toDivideSafe, TonSkuSchema, getConditionMatchStr } from "qqlx-cdk";

import { User as OldUser } from "../../../qqlx.old/qqlx-core";
import { Corp as OldCorp } from "../../../qqlx.old/qqlx-core";
import { Order as OldOrder, ENUM_ORDER } from "../../../qqlx.old/qqlx-core";
import { Sku } from "../../../qqlx.old/qqlx-core";

import { TonSkuDao } from "../dao/river";
import { ENUM_POUNDS_FORMULA } from "../../../qqlx.old/qqlx-core";
import { doBashPrint } from "../lib/log";
import { ObjectId } from "mongodb";
import { getTradeId } from "../lib/crypto";

export async function doTonSkuAdjustInsert(
  corpId: OldCorp["_id"],
  oldToNewUserMap: Map<OldUser["_id"], User>,
  oldToNewOrderMap: Map<OldUser["_id"], TonOrder>,
) {
  const mongodbClient = new MongodbClient("mongodb://localhost:27017/qqlx");
  const pgClient = new PgClient("127.0.0.1", "5432", "production", "postgres", "postgres");

  try {
    // ==================== 旧数据准备 ====================
    // ==================== 旧数据准备 ====================
    // ==================== 旧数据准备 ====================
    // ==================== 旧数据准备 ====================
    // ==================== 旧数据准备 ====================
    // ==================== 旧数据准备 ====================

    console.group("\n开始迁移mongo商品库存调整数据");
    const mongoBefore = { count: 0 };
    const mongoChange = { count: 0 };

    await mongodbClient.start();
    const pgClientIns = await pgClient.start();

    const colCorps = mongodbClient.getCollection("corps");
    const corp = (await colCorps.findOne<OldCorp>({ _id: corpId as unknown as ObjectId })) as OldCorp;
    const corpQuery = { corpId: corp._id as unknown as ObjectId };

    // 历史库存调整订单
    const orderQuery = { ...corpQuery, type: ENUM_ORDER.GETIN, parentOrderId: "" };
    const colOrders = mongodbClient.getCollection("orders");
    const oldGetinOrders = await colOrders.find<OldOrder>(orderQuery).toArray();
    console.log("旧数据（库存调整订单）", oldGetinOrders.length);

    // 历史库存调整商品
    const colSkus = mongodbClient.getCollection("skus");
    const skuQuery = { orderId: { $in: oldGetinOrders.map((d) => d._id) } };
    const oldGetinSkus = await colSkus.find<Sku>({ ...corpQuery, ...skuQuery }).toArray();
    console.log("旧数据（库存调整商品）", oldGetinSkus.length);
    mongoBefore.count = oldGetinSkus.length;

    /** 根据库存调整订单id，查询库存调整商品 */
    const oldGetinSkuMap = new Map<string, Sku[]>();
    for (const getinSku of oldGetinSkus) {
      const pid = getinSku.orderId;
      if (!oldGetinSkuMap.has(pid)) oldGetinSkuMap.set(pid, []);
      oldGetinSkuMap.get(pid)!.push(getinSku);
    }

    // ==================== 新数据准备 ====================
    // ==================== 新数据准备 ====================
    // ==================== 新数据准备 ====================
    // ==================== 新数据准备 ====================
    // ==================== 新数据准备 ====================
    // ==================== 新数据准备 ====================

    const skuDao = new TonSkuDao(pgClientIns.getRepository<TonSku>(TonSkuSchema));

    const master = oldToNewUserMap.get(corp.userId) as User;
    const condisMaster = [getConditionMatchStr("refOwnerUUid32", master.uuid32), getConditionMatchEnum("type", ENUM_TON_ORDER.ADJUST)];

    const pgCount = await skuDao.count(condisMaster);
    if (pgCount === 0) {
      const schemaLs: TonSku[] = [];
      oldGetinOrders.map((oldGetinOrder, index) => {
        for (const getinSku of oldGetinSkuMap.get(oldGetinOrder._id) || []) {
          const fromOrder = oldToNewOrderMap.get(oldGetinOrder._id) as TonOrder;

          const schema = getDefaultSku(getinSku);
          schema.refOwnerUUid32 = fromOrder.refOwnerUUid32;
          schema.refCreatorId = fromOrder.refCreatorId;
          schema.refContactId = fromOrder.refContactId;
          schema.tradeId = getTradeId();
          schema.tradeTime = fromOrder.tradeTime;
          schema.tradeYear = fromOrder.tradeYear;
          schema.tradeMonth = fromOrder.tradeMonth;
          schema.tradeScope = fromOrder.tradeScope;
          schema.type = ENUM_TON_ORDER.ADJUST;

          schema.refTonOrderGroupId = fromOrder.refTonOrderGroupId;
          schema.refTonOrderId = fromOrder.uuid32;
          schema.isOrderDisabled = fromOrder.isDisabled;

          schema.formulaName = getinSku.formula === ENUM_POUNDS_FORMULA.TS_PLATE ? "冷轧板过磅公式" : ""; // 税额如果大于0，表示需要公式
          schema.formulaContent = getinSku.formula === ENUM_POUNDS_FORMULA.TS_PLATE ? "7.85*(A/10)*(B/10)*(C/10)/1000/1000" : "";
          schemaLs.push(schema);
        }
      });

      // 1.迁移库存调整/库存调整商品
      const batchCount = 2000;
      const createds: TonSku[] = [];
      while (schemaLs.length > 0) {
        const part = schemaLs.splice(0, batchCount);
        const ls = await skuDao.insertManyAndQuery(part);
        createds.push(...ls);
        doBashPrint(`正在推送商品（${batchCount}）剩余${schemaLs.length}`);
      }
      mongoChange.count += createds.length;
    }

    // ==================== 结束 ====================
    // ==================== 结束 ====================
    // ==================== 结束 ====================
    // ==================== 结束 ====================
    // ==================== 结束 ====================
    // ==================== 结束 ====================

    const pgCountFinal = await skuDao.count(condisMaster);
    console.log(`mg目标迁移数字🔴期望/已迁移`, mongoBefore.count, mongoChange.count);
    console.log(`pg数据库记录🟢变动前/变动后`, pgCount, pgCountFinal, "变动误差", pgCountFinal - pgCount);
    console.groupEnd();
    console.log("====================================");
  } finally {
    await pgClient.stop();
    await mongodbClient.stop();
  }
}

function getDefaultSku(old: Sku) {
  const schema: TonSku = new TonSkuSchema();
  schema.name = old.name;
  schema.norm = old.norm;
  schema.unit = old.unit;
  schema.remark = old.remark;

  schema.count = old.count;
  schema.price = 0;

  const md5 = new Md5();
  md5.appendStr([schema.name, schema.norm, schema.unit].filter((e) => !!e).join("_"));
  schema.ivid = md5.end() as string;
  schema.ton = old.isPriceInPounds ? toDivideSafe(old.pounds, 1000, 3) : 0;
  schema.isTonAble = old.isPriceInPounds;

  schema.timeCreate = old.timeCreate.toString();
  schema.timeUpdate = old.timeUpdate.toString();
  return schema;
}
